Reactã§åŒ·åãã€ææ°ã®ãã©ãŒã æ€èšŒãå®çŸããŸãããããã®å æ¬çãªã¬ã€ãã§ã¯ãexperimental_useForm_Statusããã¯ããµãŒããŒã¢ã¯ã·ã§ã³ãããã³å ç¢ã§é«æ§èœãªãã©ãŒã ãæ§ç¯ããããã®ã¹ããŒã¿ã¹æ€èšŒãã©ãã€ã ã«ã€ããŠè§£èª¬ããŸãã
Reactã®`experimental_useFormStatus`ã§ãã©ãŒã æ€èšŒããã¹ã¿ãŒãã
ãã©ãŒã ã¯ãŠã§ãã€ã³ã¿ã©ã¯ã·ã§ã³ã®åºç€ã§ããã·ã³ãã«ãªãã¥ãŒã¹ã¬ã¿ãŒã®ç»é²ããè€éãªå€æ®µéã®éèã¢ããªã±ãŒã·ã§ã³ãŸã§ããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ãšéä¿¡ããããã®äž»èŠãªãã£ãã«ã§ããããããé·å¹Žã«ããããReactã§ã®ãã©ãŒã ç¶æ ã®ç®¡çã¯ãè€éãããã€ã©ãŒãã¬ãŒããäŸåé¢ä¿ã®ç²åŽã®åå ãšãªã£ãŠããŸãããç§ãã¡ã¯ãå¶åŸ¡ãããã³ã³ããŒãã³ããããããããç¶æ 管çã©ã€ãã©ãªãšæ Œéããæ°ãåããªãã»ã©ã®`onChange`ãã³ãã©ãŒãèšè¿°ãããã¹ãŠã·ãŒã ã¬ã¹ã§çŽæçãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã远æ±ããŠããŸããã
ReactããŒã ã¯ããŠã§ãéçºã®ãã®åºæ¬çãªåŽé¢ãåèããReact Server Actionsãäžå¿ãšããæ°ãã匷åãªãã©ãã€ã ã®å°å ¥ã«ã€ãªãããŸããããã®æ°ããã¢ãã«ã¯ãããã°ã¬ãã·ããšã³ãã³ã¹ã¡ã³ãã®ååã«åºã¥ããŠæ§ç¯ãããŠãããããžãã¯ãæ¬æ¥ããã¹ãå Žæãã€ãŸãå€ãã®å ŽåãµãŒããŒã«è¿ã¥ããããšã§ããã©ãŒã åŠçãç°¡çŽ åããããšãç®çãšããŠããŸãããã®ã¯ã©ã€ã¢ã³ãåŽã®é©åœã®äžå¿ã«ããã®ã¯ã2ã€ã®æ°ããå®éšçãªããã¯ã`useFormState`ãšã仿¥ã®è°è«ã®äž»åœ¹ã§ãã`experimental_useFormStatus`ã§ãã
ãã®å æ¬çãªã¬ã€ãã§ã¯ã`experimental_useFormStatus`ããã¯ãæ·±ãæãäžããŠãããŸãããã®æ§æãèŠãã ãã§ãªãããããå¯èœã«ããã¡ã³ã¿ã«ã¢ãã«ãã€ãŸãã¹ããŒã¿ã¹ããŒã¹ã®æ€èšŒããžãã¯ãæ¢æ±ããŸãããã®ããã¯ãUIããã©ãŒã ç¶æ ããåé¢ããä¿çç¶æ ã®ç®¡çãç°¡çŽ åãããµãŒããŒã¢ã¯ã·ã§ã³ãšé£æºããŠãJavaScriptãããŒããããåã§ãæ©èœããå ç¢ã§ã¢ã¯ã»ã¹å¯èœããã€éåžžã«é«æ§èœãªãã©ãŒã ãäœæããæ¹æ³ãåŠã³ãŸããReactã§ãã©ãŒã ãæ§ç¯ããããšã«ã€ããŠç¥ã£ãŠãããšæã£ãŠãããã¹ãŠã®ããšãåèããæºåãããŠãã ããã
ãã©ãã€ã ã·ãã: Reactãã©ãŒã ã®é²å
`useFormStatus`ããããã驿°æ§ãååã«çè§£ããã«ã¯ããŸãReactãšã³ã·ã¹ãã ã«ããããã©ãŒã 管çã®éã®ããçè§£ããå¿ èŠããããŸãããã®æèã¯ããã®æ°ããã¢ãããŒãããšã¬ã¬ã³ãã«è§£æ±ºããåé¡ãæµ®ã圫ãã«ããŸãã
æ§äœå¶: å¶åŸ¡ãããã³ã³ããŒãã³ããšãµãŒãããŒãã£ã©ã€ãã©ãª
é·å¹Žã«ããããReactã«ããããã©ãŒã ãžã®æšæºçãªã¢ãããŒãã¯ãå¶åŸ¡ãããã³ã³ããŒãã³ããã¿ãŒã³ã§ãããããã«ã¯ä»¥äžãå«ãŸããŸã:
- åãã©ãŒã å ¥åã®å€ãä¿æããããã«ãReactç¶æ 倿°ïŒäŸ: `useState`ããïŒã䜿çšããŸãã
- ãã¹ãŠã®ããŒã¹ãããŒã¯ã§ç¶æ ãæŽæ°ãã`onChange`ãã³ãã©ãŒãèšè¿°ããŸãã
- ç¶æ 倿°ãå ¥åã®`value`ããããã«æž¡ããŸãã
ããã«ãããReactã¯ãã©ãŒã ã®ç¶æ ãå®å šã«å¶åŸ¡ã§ããŸãããããªãã®ãã€ã©ãŒãã¬ãŒããå°å ¥ãããŸãã10åã®ãã£ãŒã«ããæã€ãã©ãŒã ã®å Žåã10åã®ç¶æ 倿°ãš10åã®ãã³ãã©ãŒé¢æ°ãå¿ èŠã«ãªãå ŽåããããŸããæ€èšŒããšã©ãŒç¶æ ãããã³éä¿¡ã¹ããŒã¿ã¹ã管çãããšãããã«è€éããå¢ããå€ãã®å Žåãéçºè ã¯è€éãªã«ã¹ã¿ã ããã¯ãäœæããããå æ¬çãªãµãŒãããŒãã£ã©ã€ãã©ãªãæ¢ãããããããšã«ãªããŸãã
FormikãReact Hook Formãªã©ã®ã©ã€ãã©ãªã¯ããã®è€éããæœè±¡åããããšã§æ³šç®ãéããŸããããããã¯ãç¶æ 管çãæ€èšŒãããã³ããã©ãŒãã³ã¹ã®æé©åã®ããã®åªãããœãªã¥ãŒã·ã§ã³ãæäŸããŸãããã ãããããã¯ç®¡çããå¥ã®äŸåé¢ä¿ã衚ããŠãããå€ãã®å Žåãã¯ã©ã€ã¢ã³ãåŽã§ã®ã¿åäœãããããããã³ããšã³ããšããã¯ãšã³ãéã§æ€èšŒããžãã¯ãéè€ããå¯èœæ§ããããŸãã
æ°æä»£: ããã°ã¬ãã·ããšã³ãã³ã¹ã¡ã³ããšãµãŒããŒã¢ã¯ã·ã§ã³
React Server Actionsã¯ããã©ãã€ã ã·ããããããããŸããäžå¿ãšãªãèãæ¹ã¯ããŠã§ããã©ãããã©ãŒã ã®åºç€ã§ããæšæºã®HTML `
ç°¡åãªäŸ: ã¹ããŒãéä¿¡ãã¿ã³
æãäžè¬çãªãŠãŒã¹ã±ãŒã¹ãèŠãŠã¿ãŸããããæšæºã®`
ãã¡ã€ã«: SubmitButton.js
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
export function SubmitButton() {
const { pending } = useFormStatus();
return (
);
}
ãã¡ã€ã«: SignUpForm.js
import { SubmitButton } from './SubmitButton';
import { signUpAction } from './actions'; // A server action
export function SignUpForm() {
return (
ãã®äŸã§ã¯ã`SubmitButton`ã¯å®å šã«èªå·±å®çµåã§ãããããããåãåããŸããã`useFormStatus`ã䜿çšããŠã`SignUpForm`ããã€ä¿çäžã§ããããç¥ããèªåçã«èªåèªèº«ãç¡å¹ã«ããããã¹ãã倿ŽããŸããããã¯ãåé¢ãè¡ããåå©çšå¯èœãªãã©ãŒã 察å¿ã³ã³ããŒãã³ããäœæããããã®åŒ·åãªãã¿ãŒã³ã§ãã
æ¬è³ª: ã¹ããŒã¿ã¹ããŒã¹ã®æ€èšŒããžãã¯
ããã§ãã³ã¢ã³ã³ã»ããã«å°éããŸãã`useFormStatus`ã¯ãåã«ããŒãã£ã³ã°ç¶æ ã®ããã ãã®ãã®ã§ã¯ãããŸãããæ€èšŒã«é¢ããç°ãªãèãæ¹ãå®çŸããããã®éèŠãªèŠçŽ ã§ãã
ãã¹ããŒã¿ã¹æ€èšŒãã®å®çŸ©
ã¹ããŒã¿ã¹ããŒã¹ã®æ€èšŒã¯ãæ€èšŒãã£ãŒãããã¯ãäž»ã«ãã©ãŒã éä¿¡ã®è©Šè¡ã«å¿ããŠãŠãŒã¶ãŒã«é ä¿¡ããããã¿ãŒã³ã§ãããã¹ãŠã®ããŒã¹ãããŒã¯ïŒ`onChange`ïŒãŸãã¯ãŠãŒã¶ãŒããã£ãŒã«ããé¢ãããšãïŒ`onBlur`ïŒã«æ€èšŒãã代ããã«ãäž»èŠãªæ€èšŒããžãã¯ã¯ãŠãŒã¶ãŒããã©ãŒã ãéä¿¡ãããšãã«å®è¡ãããŸãããã®éä¿¡ã®çµæïŒãã®*ã¹ããŒã¿ã¹*ãäŸ: æåãæ€èšŒãšã©ãŒããµãŒããŒãšã©ãŒïŒã¯ãUIãæŽæ°ããããã«äœ¿çšãããŸãã
ãã®ã¢ãããŒãã¯ãReact Server Actionsãšå®å šã«äžèŽããŸãããµãŒããŒã¢ã¯ã·ã§ã³ã¯ãæ€èšŒã®åäžã®çå®ã®æºã«ãªããŸãããã©ãŒã ããŒã¿ãåãåããããžãã¹ã«ãŒã«ïŒäŸ: ããã®ã¡ãŒã«ã¢ãã¬ã¹ã¯ãã§ã«äœ¿çšãããŠããŸããïŒãïŒã«å¯ŸããŠæ€èšŒããçµæãç€ºãæ§é åãããç¶æ ãªããžã§ã¯ããè¿ããŸãã
ããŒãããŒã®åœ¹å²: `experimental_useFormState`
`useFormStatus`ã¯äœãèµ·ãã£ãŠãããïŒä¿çäžïŒãæããŠãããŸãããäœãèµ·ãã£ããã®*çµæ*ã¯æããŠãããŸããããã®ããã«ã¯ãå åŒããã¯ã§ãã`experimental_useFormState`ãå¿ èŠã§ãã
`useFormState`ã¯ããã©ãŒã ã¢ã¯ã·ã§ã³ã®çµæã«åºã¥ããŠç¶æ ãæŽæ°ããããã«èšèšãããããã¯ã§ããã¢ã¯ã·ã§ã³é¢æ°ãšåæç¶æ ãåŒæ°ãšããŠåãåããæ°ããç¶æ ãšãã©ãŒã ã«æž¡ãã©ãããããã¢ã¯ã·ã§ã³é¢æ°ãè¿ããŸãã
const [state, formAction] = useFormState(myAction, initialState);
- `state`: ããã«ã¯ã`myAction`ã®æåŸã®å®è¡ããã®æ»ãå€ãå«ãŸããŸããããã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ãããŸãã
- `formAction`: ããã¯ã`
`ã®`action`ããããã«æž¡ãå¿ èŠã®ããã¢ã¯ã·ã§ã³ã®æ°ããããŒãžã§ã³ã§ãããããåŒã³åºããããšãå ã®ã¢ã¯ã·ã§ã³ãããªã¬ãŒããã`state`ãæŽæ°ãããŸãã
çµã¿åãããã¯ãŒã¯ãããŒ: ã¯ãªãã¯ãããã£ãŒãããã¯ãŸã§
`useFormState`ãš`useFormStatus`ã飿ºããŠå®å šãªæ€èšŒã«ãŒããäœæããæ¹æ³ã次ã«ç€ºããŸã:
- åæã¬ã³ããªã³ã°: ãã©ãŒã ã¯ã`useFormState`ã«ãã£ãŠæäŸãããåæç¶æ ã§ã¬ã³ããªã³ã°ãããŸãããšã©ãŒã¯è¡šç€ºãããŸããã
- ãŠãŒã¶ãŒéä¿¡: ãŠãŒã¶ãŒãéä¿¡ãã¿ã³ãã¯ãªãã¯ããŸãã
- ä¿çäžã®ç¶æ : éä¿¡ãã¿ã³ã®`useFormStatus`ããã¯ã¯ãããã«`pending: true`ãå ±åããŸãããã¿ã³ãç¡å¹ã«ãªããããŒãã£ã³ã°ã¡ãã»ãŒãžã衚瀺ãããŸãã
- ã¢ã¯ã·ã§ã³ã®å®è¡: ãµãŒããŒã¢ã¯ã·ã§ã³ïŒ`useFormState`ã«ãã£ãŠã©ããïŒã¯ããã©ãŒã ããŒã¿ãšãšãã«å®è¡ãããŸããæ€èšŒãå®è¡ããŸãã
- ã¢ã¯ã·ã§ã³ã®æ»ã: ã¢ã¯ã·ã§ã³ãæ€èšŒã«å€±æããç¶æ
ãªããžã§ã¯ããè¿ããŸããäŸ:
`{ message: "Validation failed", errors: { email: "This email is already taken." } }` - ç¶æ ã®æŽæ°: `useFormState`ã¯ãã®æ»ãå€ãåãåãã`state`倿°ãæŽæ°ããŸããããã«ããããã©ãŒã ã³ã³ããŒãã³ãã®åã¬ã³ããªã³ã°ãããªã¬ãŒãããŸãã
- UIãã£ãŒãããã¯: ãã©ãŒã ãåã¬ã³ããªã³ã°ãããŸãã`useFormStatus`ããã®`pending`ã¹ããŒã¿ã¹ã¯`false`ã«ãªããŸããã³ã³ããŒãã³ãã¯ã`state.errors.email`ãèªã¿åããã¡ãŒã«å ¥åãã£ãŒã«ãã®æšªã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ã§ããŸãã
ãã®ãããŒå šäœã¯ãéä¿¡ã¹ããŒã¿ã¹ãšçµæã«ãã£ãŠå®å šã«é§åããããæç¢ºã§ãµãŒããŒã«ããä¿¡é Œã§ãããã£ãŒãããã¯ããŠãŒã¶ãŒã«æäŸããŸãã
å®è·µçãªãã¹ã¿ãŒã¯ã©ã¹: è€æ°ãã£ãŒã«ãã®ç»é²ãã©ãŒã ã®æ§ç¯
å®å šãªæ¬çªã¹ã¿ã€ã«ã®ç»é²ãã©ãŒã ãæ§ç¯ããããšã§ããããã®æŠå¿µãå ·äœåããŸããããæ€èšŒã«ã¯ãµãŒããŒã¢ã¯ã·ã§ã³ã䜿çšãã`useFormState`ãš`useFormStatus`ã®äž¡æ¹ã䜿çšããŠãåªãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãäœæããŸãã
ã¹ããã1: æ€èšŒã䜿çšãããµãŒããŒã¢ã¯ã·ã§ã³ã®å®çŸ©
ãŸãããµãŒããŒã¢ã¯ã·ã§ã³ãå¿ èŠã§ããå ç¢ãªæ€èšŒã®ããã«ãäžè¬çãªã©ã€ãã©ãªã§ããZodã䜿çšããŸãããã®ã¢ã¯ã·ã§ã³ã¯ãNext.jsã®ãããªãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠããå Žåã¯ã`'use server';`ãã£ã¬ã¯ãã£ãã§ããŒã¯ãããå¥ã®ãã¡ã€ã«ã«ååšããŸãã
ãã¡ã€ã«: actions/authActions.js
'use server';
import { z } from 'zod';
// Define the validation schema
const registerSchema = z.object({
username: z.string().min(3, 'Username must be at least 3 characters long.'),
email: z.string().email('Please enter a valid email address.'),
password: z.string().min(8, 'Password must be at least 8 characters long.'),
});
// Define the initial state for our form
export const initialState = {
message: '',
errors: {},
};
export async function registerUser(prevState, formData) {
// 1. Validate the form data
const validatedFields = registerSchema.safeParse(
Object.fromEntries(formData.entries())
);
// 2. If validation fails, return the errors
if (!validatedFields.success) {
return {
message: 'Validation failed. Please check the fields.',
errors: validatedFields.error.flatten().fieldErrors,
};
}
// 3. (Simulate) Check if user already exists in the database
// In a real app, you would query your database here.
if (validatedFields.data.email === 'user@example.com') {
return {
message: 'Registration failed.',
errors: { email: ['This email is already registered.'] },
};
}
// 4. (Simulate) Create the user
console.log('Creating user:', validatedFields.data);
// 5. Return a success state
// In a real app, you might redirect here using `redirect()` from 'next/navigation'
return {
message: 'User registered successfully!',
errors: {},
};
}
ãã®ãµãŒããŒã¢ã¯ã·ã§ã³ã¯ããã©ãŒã ã®é è³ã§ããèªå·±å®çµåã§å®å šã§ãããæåç¶æ ãšãšã©ãŒç¶æ ã®äž¡æ¹ã«å¯ŸããŠæç¢ºãªããŒã¿æ§é ãæäŸããŸãã
ã¹ããã2: åå©çšå¯èœãªã¹ããŒã¿ã¹å¯Ÿå¿ã³ã³ããŒãã³ãã®æ§ç¯
ã¡ã€ã³ã®ãã©ãŒã ã³ã³ããŒãã³ããã¯ãªãŒã³ã«ä¿ã€ããã«ãå ¥åãšéä¿¡ãã¿ã³å°çšã®ã³ã³ããŒãã³ããäœæããŸãã
ãã¡ã€ã«: components/SubmitButton.js
'use client';
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
export function SubmitButton({ label }) {
const { pending } = useFormStatus();
return (
);
}
`aria-disabled={pending}`ã®äœ¿çšã«æ³šæããŠãã ãããããã¯éèŠãªã¢ã¯ã»ã·ããªãã£ã®å®è·µã§ãããã¹ã¯ãªãŒã³ãªãŒããŒãdisabledç¶æ ãæ£ããã¢ããŠã³ã¹ããããšãä¿èšŒããŸãã
ã¹ããã3: `useFormState`ã䜿çšããã¡ã€ã³ãã©ãŒã ã®çµã¿ç«ãŠ
次ã«ãã¡ã€ã³ãã©ãŒã ã³ã³ããŒãã³ãã«ãã¹ãŠããŸãšããŸãããã`useFormState`ã䜿çšããŠãUIã`registerUser`ã¢ã¯ã·ã§ã³ã«æ¥ç¶ããŸãã
ãã¡ã€ã«: components/RegistrationForm.js
{state.message} {state.message}
{state.errors.username[0]}
{state.errors.email[0]}
{state.errors.password[0]}
'use client';
import { experimental_useFormState as useFormState } from 'react-dom';
import { registerUser, initialState } from '../actions/authActions';
import { SubmitButton } from './SubmitButton';
export function RegistrationForm() {
const [state, formAction] = useFormState(registerUser, initialState);
return (
Register
{state?.message && !state.errors &&
ãã®ã³ã³ããŒãã³ãã¯å®£èšåã§ã¯ãªãŒã³ã«ãªããŸããã`useFormState`ã«ãã£ãŠæäŸããã`state`ãªããžã§ã¯ããé€ããŠãç¶æ ã管çããŸããããã®å¯äžã®ä»äºã¯ããã®ç¶æ ã«åºã¥ããŠUIãã¬ã³ããªã³ã°ããããšã§ãããã¿ã³ãç¡å¹ã«ããããžãã¯ã¯`SubmitButton`ã«ã«ãã»ã«åããããã¹ãŠã®æ€èšŒããžãã¯ã¯`authActions.js`ã«ååšããŸãããã®é¢å¿ã®åé¢ã¯ãä¿å®æ§ã«ãšã£ãŠéåžžã«æå©ã§ãã
é«åºŠãªãã¯ããã¯ãšãããã§ãã·ã§ãã«ãªãã¹ããã©ã¯ãã£ã¹
åºæ¬çãªãã¿ãŒã³ã¯åŒ·åã§ãããå®éã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ããå€ãã®ãã¥ã¢ã³ã¹ãå¿ èŠã«ãªãããšããããããŸããããã€ãã®é«åºŠãªãã¯ããã¯ãæ¢æ±ããŸãããã
ãã€ããªããã¢ãããŒã: ã€ã³ã¹ã¿ã³ãæ€èšŒãšéä¿¡åŸæ€èšŒã®ããŒãž
ã¹ããŒã¿ã¹ããŒã¹ã®æ€èšŒã¯ããµãŒããŒåŽã®ãã§ãã¯ã«æé©ã§ããããŠãŒã¶ãŒã«ã¡ãŒã«ã¢ãã¬ã¹ãç¡å¹ã§ããããšãäŒããããã«ãããã¯ãŒã¯ã©ãŠã³ãããªãããåŸ ã€ãšãé ããªãå¯èœæ§ããããŸãããã€ããªããã¢ãããŒããæé©ãªå ŽåããããããŸã:
- HTML5æ€èšŒã®äœ¿çš: åºæ¬ãå¿ããªãã§ãã ããïŒ`required`ã`type="email"`ã`minLength`ã`pattern`ãªã©ã®å±æ§ã¯ãã³ã¹ããªãã§ã€ã³ã¹ã¿ã³ãã®ãã©ãŠã¶ãã€ãã£ããã£ãŒãããã¯ãæäŸããŸãã
- 軜éã®ã¯ã©ã€ã¢ã³ãåŽæ€èšŒ: çŽç²ã«çŸå®¹çãŸãã¯ãã©ãŒããããã§ãã¯ïŒäŸ: ãã¹ã¯ãŒã匷床ã€ã³ãžã±ãŒã¿ãŒïŒã®ããã«ãæå°éã®`useState`ãš`onChange`ãã³ãã©ãŒãåŒãç¶ã䜿çšã§ããŸãã
- ãµãŒããŒåŽã®æš©é: ã¯ã©ã€ã¢ã³ãåŽã§ã¯å®è¡ã§ããªãæãéèŠãªããžãã¹ããžãã¯æ€èšŒã®ããã«ããµãŒããŒã¢ã¯ã·ã§ã³ãäºçŽããŸãïŒäŸ: äžæã®ãŠãŒã¶ãŒåã®ãã§ãã¯ãããŒã¿ããŒã¹ã¬ã³ãŒãã«å¯Ÿããæ€èšŒïŒã
ããã«ãããåçŽãªãšã©ãŒã«å¯Ÿãã峿ãã£ãŒãããã¯ãšãè€éãªã«ãŒã«ã«å¯Ÿããä¿¡é Œã§ããæ€èšŒãšãããäž¡æ¹ã®é·æãåŸãããŸãã
ã¢ã¯ã»ã·ããªã㣠(A11y): ãã¹ãŠã®äººã®ããã®ãã©ãŒã ã®æ§ç¯
ã¢ã¯ã»ã·ããªãã£ã¯äº€æžã®äœå°ããããŸãããã¹ããŒã¿ã¹ããŒã¹ã®æ€èšŒãå®è£ ããå Žåã¯ã次ã®ç¹ã念é ã«çœ®ããŠãã ãã:
- ãšã©ãŒã®ã¢ããŠã³ã¹: äŸã§ã¯ããšã©ãŒã¡ãã»ãŒãžã³ã³ãããŒã§`aria-live="polite"`ã䜿çšããŸãããããã«ãããã¹ã¯ãªãŒã³ãªãŒããŒã¯ããŠãŒã¶ãŒã®çŸåšã®ãããŒãäžæããããšãªãããšã©ãŒã¡ãã»ãŒãžã衚瀺ããããšããã«ã¢ããŠã³ã¹ããããã«æç€ºãããŸãã
- ãšã©ãŒã®å ¥åãé¢é£ä»ããŸã: ããå ç¢ãªæ¥ç¶ã®ããã«ã`aria-describedby`屿§ã䜿çšããŸããå ¥åã¯ããã®ãšã©ãŒã¡ãã»ãŒãžã³ã³ãããŒã®IDãæããããã°ã©ã ã«ãããªã³ã¯ãäœæã§ããŸãã
- ãã©ãŒã«ã¹ã®ç®¡ç: ãšã©ãŒã®ããéä¿¡ã®åŸãæåã®ç¡å¹ãªãã£ãŒã«ãã«ããã°ã©ã ã§ãã©ãŒã«ã¹ãç§»åããããšãæ€èšããŠãã ãããããã«ããããŠãŒã¶ãŒã¯äœãééã£ãŠããã®ããæ€çŽ¢ããå¿ èŠããªããªããŸãã
`useFormStatus`ã®`data`ããããã£ã䜿çšããæ¥œèгçãªUI
ãŠãŒã¶ãŒãã³ã¡ã³ããæçš¿ãããœãŒã·ã£ã«ã¡ãã£ã¢ã¢ããªãæ³åããŠã¿ãŠãã ããã1ç§éã¹ãããŒã衚瀺ãã代ããã«ãã¢ããªãç¬æã«æããããããšãã§ããŸãã`useFormStatus`ã®`data`ããããã£ã¯ããã«æé©ã§ãã
ãã©ãŒã ãéä¿¡ããããšã`pending`ãtrueã«ãªãã`data`ã«éä¿¡ã®`FormData`ãå ¥åãããŸãããã®`data`ã䜿çšããŠãäžæçãªãä¿çäžãã®èŠèŠç¶æ ã§ããã«æ°ããã³ã¡ã³ããã¬ã³ããªã³ã°ã§ããŸãããµãŒããŒã¢ã¯ã·ã§ã³ãæåãããšãä¿çäžã®ã³ã¡ã³ãããµãŒããŒããã®æçµããŒã¿ã«çœ®ãæããŸãã倱æããå Žåã¯ãä¿çäžã®ã³ã¡ã³ããåé€ããŠãšã©ãŒã衚瀺ã§ããŸããããã«ãããã¢ããªã±ãŒã·ã§ã³ã¯éåžžã«å¿çæ§ãé«ããªããŸãã
ãå®éšçããªæµ·åã®ããã²ãŒã
`experimental_useFormStatus`ããã³`experimental_useFormState`ã®ãexperimentalããã¬ãã£ãã¯ã¹ã«å¯ŸåŠããããšãéèŠã§ãã
ãå®éšçããå®éã«æå³ããããš
ReactãAPIãå®éšçãšã©ãã«ä»ãããå Žåãããã¯æ¬¡ã®ããšãæå³ããŸã:
- APIã倿Žãããå¯èœæ§ããããŸã: ååãåŒæ°ããŸãã¯æ»ãå€ã¯ãç Žå£çãªå€æŽã®ããã®æšæºçãªã»ãã³ãã£ãã¯ããŒãžã§ãã³ã°ïŒSemVerïŒã«åŸããã«ãå°æ¥ã®ReactãªãªãŒã¹ã§å€æŽãããå¯èœæ§ããããŸãã
- ãã°ãããå¯èœæ§ããããŸã: æ°ããæ©èœãšããŠããŸã å®å šã«çè§£ãŸãã¯è§£æ±ºãããŠããªããšããžã±ãŒã¹ãããå¯èœæ§ããããŸãã
- ããã¥ã¡ã³ãããŸã°ãã§ããå¯èœæ§ããããŸã: ã³ã¢ã³ã³ã»ããã¯ææžåãããŠããŸãããé«åºŠãªãã¿ãŒã³ã«é¢ãã詳现ãªã¬ã€ãã¯ãŸã é²åããŠããå¯èœæ§ããããŸãã
ãã€æ¡çšãããã€åŸ ã€ã
ã§ã¯ããããžã§ã¯ãã§äœ¿çšããå¿ èŠããããŸããïŒçãã¯ã³ã³ããã¹ãã«ãã£ãŠç°ãªããŸã:
- æšå¥š: å人çãªãããžã§ã¯ããå éšããŒã«ãã¹ã¿ãŒãã¢ããããŸãã¯æœåšçãªAPIã®å€æŽã®ç®¡çã«æ £ããŠããããŒã ããããã®æ©èœãApp Routerã«çµ±åããNext.jsã®ãããªãã¬ãŒã ã¯ãŒã¯å ã§äœ¿çšããããšã¯ããã¬ãŒã ã¯ãŒã¯ãäžéšã®ãã£ãŒã³ãæœè±¡åããã®ã«åœ¹ç«ã€ãããäžè¬çã«å®å šãªè³ãã§ãã
- 泚æããŠäœ¿çšããŠãã ãã: å€§èŠæš¡ãªãšã³ã¿ãŒãã©ã€ãºã¢ããªã±ãŒã·ã§ã³ãããã·ã§ã³ã¯ãªãã£ã«ã«ãªã·ã¹ãã ããŸãã¯APIã®å®å®æ§ãæãéèŠãªé·æã¡ã³ããã³ã¹å¥çŽã®ãããããžã§ã¯ãããããã®å Žåãããã¯ãå®å®ããAPIã«ææ ŒãããŸã§åŸ ã€ã®ãè³¢æãããããŸããã
ãããã®ããã¯ã®å®å®åã«é¢ããçºè¡šã«ã€ããŠã¯ãå ¬åŒã®Reactããã°ãšããã¥ã¡ã³ãã«åžžã«æ³šæããŠãã ããã
çµè«: Reactã«ããããã©ãŒã ã®æªæ¥
`experimental_useFormStatus`ããã³é¢é£ããAPIã®å°å ¥ã¯ãåãªãæ°ããããŒã«ã§ã¯ãããŸãããããã¯ãReactã§ã€ã³ã¿ã©ã¯ãã£ããªãšã¯ã¹ããªãšã³ã¹ãæ§ç¯ããæ¹æ³ã«ãããå²åŠçãªå€åã衚ããŠããŸãããŠã§ããã©ãããã©ãŒã ã®åºç€ãåãå ¥ããã¹ããŒããã«ããžãã¯ããµãŒããŒäžã«å ±åé 眮ããããšã§ãããã·ã³ãã«ã§ãããå埩åããããå€ãã®å Žåãããããã©ãŒãã³ã¹ã®é«ãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãã
`useFormStatus`ããã³ã³ããŒãã³ãããã©ãŒã éä¿¡ã®ã©ã€ããµã€ã¯ã«ã«åå¿ããããã®ã¯ãªãŒã³ã§åé¢ãããæ¹æ³ãã©ã®ããã«æäŸããããèŠãŠããŸãããä¿çäžã®ç¶æ ã«å¯Ÿããããããããªãªã³ã°ãæé€ããã¹ããŒã`SubmitButton`ã®ãããªãšã¬ã¬ã³ãã§èªå·±å®çµåã®UIã³ã³ããŒãã³ããå¯èœã«ããŸãã`useFormState`ãšçµã¿åããããšãã¹ããŒã¿ã¹ããŒã¹ã®æ€èšŒãšãã匷åãªãã¿ãŒã³ãã¢ã³ããã¯ãããŸãããã®ãã¿ãŒã³ã§ã¯ããµãŒããŒãç©¶æ¥µã®æš©éã§ãããã¯ã©ã€ã¢ã³ãã®äž»ãªè²¬ä»»ã¯ããµãŒããŒã¢ã¯ã·ã§ã³ã«ãã£ãŠè¿ãããç¶æ ãã¬ã³ããªã³ã°ããããšã§ãã
ãå®éšçãã¿ã°ã¯ããçšåºŠã®æ³šæãå¿ èŠãšããŸãããæ¹åæ§ã¯æç¢ºã§ããReactã«ããããã©ãŒã ã®æªæ¥ã¯ãããã°ã¬ãã·ããšã³ãã³ã¹ã¡ã³ããç°¡çŽ åãããç¶æ 管çãããã³ã¯ã©ã€ã¢ã³ãããžãã¯ãšãµãŒããŒããžãã¯éã®åŒ·åã§ã·ãŒã ã¬ã¹ãªçµ±åã®1ã€ã§ãã仿¥ãããã®æ°ããããã¯ããã¹ã¿ãŒããããšã§ãæ°ããAPIãåŠã¶ã ãã§ãªããReactã䜿çšããæ¬¡äžä»£ã®ãŠã§ãã¢ããªã±ãŒã·ã§ã³éçºã«åããŠããŸãã